home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Programming / GedEiffel / tools / eiffel / arexx / console.rexx next >
OS/2 REXX Batch file  |  1999-01-24  |  9KB  |  302 lines

  1. /****** console.rexx *******************************************************
  2.  * NAME
  3.  *    console.rexx -- Output console to execute CLI commands.
  4.  * INPUTS
  5.  *    Port/K
  6.  *       Portname to create and to which commands can be sent. If ommited,
  7.  *       "CONSOLE.1" is used.
  8.  *    Debug/S
  9.  *       Enable debugging messages.
  10.  * FUNCTION
  11.  *    Start the console and waits for commands.
  12.  *
  13.  *    (This script is automatically invoked by execute.rexx, if the
  14.  *    requested port does not yet exist.)
  15.  *
  16.  *    Commands can be executed by sending them as ARexx messages to the port
  17.  *    Preferable this should be done calling the script execute.rexx.
  18.  *
  19.  *    All command are assumed to be normal CLI commands like "list", "echo"
  20.  *    or "type". However, there are a view exceptions:
  21.  *
  22.  *    QUIT
  23.  *       Quits the console and removes its message port. For compatibility,
  24.  *       ENDCLI and ENDSHELL work the same.
  25.  *    CD [`directory']
  26.  *       The normal CD command does not work because the previous current
  27.  *       directory is restored once ADDRESS COMMAND returns. Therefore,
  28.  *       this command has to be emulated by the shell.
  29.  *
  30.  *       The emulation works pretty much the same. However, relativ paths
  31.  *       are not relative to the invoking shell, but to the current
  32.  *       directory of the console:
  33.  *
  34.  *          CD "ram:"
  35.  *             Change current directory to "ram:"
  36.  *          CD hugo/sepp
  37.  *             Change to "hugo/sepp" relative to the current directory of
  38.  *             the console.
  39.  *          CD
  40.  *             Display current directory in console. Works like PWD under
  41.  *             other systems. This, by the way, simulates the behavior of
  42.  *             the original c:CD.
  43.  *    CD-INTERNAL `directory'
  44.  *       Changes the current of the console to the one specified, but only
  45.  *       if its not already there anyway. If no CD is necessary, no command
  46.  *       is executed and nothing is displayed in the console.
  47.  *
  48.  *       See NOTES below for more details.
  49.  * EXAMPLES
  50.  *    In most cases, you will like to redirect the output of the shell to
  51.  *    one window reserved for it. Furthermore, you will want to it to run
  52.  *    as a task in the background:
  53.  *
  54.  *       run <>nil: rx console.rexx
  55.  *                  >con:////Console/AUTO/CLOSE/WAIT/INACTIVE
  56.  *
  57.  *    Because of AUTO, you can close the window when it is not needed. Once
  58.  *    new commands arrive, it automatically reopens. Because of INACTIVE,
  59.  *    the window will not change to the current window once it opens. This
  60.  *    avoids that you are distract from your editor or other developer
  61.  *    tools.
  62.  *
  63.  *    An even more useful variant is:
  64.  *
  65.  *       run <>nil: rx rexx:console.rexx
  66.  *                  >con:0/4096/512/96/Console/
  67.  *                  AUTO/CLOSE/WAIT/INACTIVE/
  68.  *                  ALT0/4096/512/400/SCREENGOLDED.1
  69.  *
  70.  *    ALT is used to specify the window size when the zoom-gadget is
  71.  *    clicked. Here the normal size is very small so the window does not
  72.  *    waste much space on the screen. But in case of something happening
  73.  *    (e.g. loads of compiler errors), only one mouse-click results in a
  74.  *    nice, big window. Finally, SCREENGOLDED.1 causes the window to pop-up
  75.  *    on a public screen named GOLDED.1, where usually GoldEd is running.
  76.  *
  77.  *    If you just want to shell to share your current CLI without running
  78.  *    in the background, simply use
  79.  *
  80.  *       rx console.rexx
  81.  *
  82.  *    In that case however you still need a second CLI to send command to
  83.  *    the shell because it does not read from the console but from its
  84.  *    ARexx port.
  85.  * NOTES
  86.  *    The execute.rexx scripts *always* executes a CD-INTERNAL with the
  87.  *    current directory of the invoking CLI. This avoids a lot of problems
  88.  *    if you stick to using this script.
  89.  * COPYRIGHT
  90.  *    Copyright (C) 1999 Thomas Aglassinger <agi@sbox.tu-graz.ac.at>
  91.  *    Freeware. Use at your own risk.
  92.  * SEE ALSO
  93.  *    execute.rexx
  94.  **************************************************************************/
  95. version_info = "$VER: console.rexx 1.2 (24.1.99)"
  96.  
  97. Options FailAt 21
  98.  
  99. Signal On Failure
  100. Signal On NoValue
  101.  
  102. template = 'Port/K,Auto/S,Debug/S'
  103. port = 'CONSOLE.1'
  104. auto = 0
  105. debug = 0
  106.  
  107. LF = d2c(10)
  108. CR = d2c(13)
  109. ESC = d2c(27)
  110. BS = d2c(8)
  111.  
  112. Call add_library('rexxsupport.library', 0)
  113. Call add_library('rexxdossupport.library', 0)
  114.  
  115. /* Check Arguments */
  116. Parse Arg arguments
  117.  
  118. If Strip(arguments, 'B', ' "') = '?' then do
  119.    Call WriteCh('STDOUT', template || ': ')
  120.    Pull arguments
  121. end
  122.  
  123. if ~ReadArgs(arguments, template) then do
  124.    Say "Error in arguments: " || Fault(RC)
  125.    Exit 10
  126. end
  127.  
  128. if OpenPort(port) then do
  129.  
  130.    command_counter = 0
  131.    show_prompt = 0
  132.  
  133.    if ~auto then do
  134.       Call say_prompt()
  135.    end
  136.  
  137.    quit = 0
  138.    do until quit
  139.       /* Wait for command */
  140.       Call WaitPkt(port)
  141.       packet = GetPkt(port)
  142.  
  143.       /* Reset return value */
  144.       rv = 0
  145.  
  146.       real_message = packet ~= null()
  147.       if real_message then do
  148.  
  149.          /* Obtain command */
  150.          command = GetArg(packet)
  151.          command = Strip(command,'L')
  152.  
  153.          /* Strip a possible surrounding pair of quotes */
  154.          if (Right(command,1) = '"') & (Left(command,1) = '"') then do
  155.             command = SubStr(command, 2, Length(command) - 2)
  156.          end
  157.  
  158.          quit = (Find('QUIT ENDSHELL ENDCLI', Upper(command)) > 0)
  159.          if ~quit then do
  160.             first_word = Upper(Word(command, 1))
  161.             if (first_word = 'CD') | (first_word = 'CD-INTERNAL') then do
  162.                /* Execute "CD" command */
  163.                if Words(command) > 1 then do
  164.                   directory = SubStr(command, WordIndex(command,2))
  165.                end
  166.                else do
  167.                   directory = ''
  168.                end
  169.                directory = Strip(Strip(directory, 'B'), 'B', '"')
  170.                current_directory = Pragma('Directory')
  171.                if directory ~= '' then do
  172.                   /* Change current directory */
  173.                   Call say_debug( first_word || ' from "' || current_directory || '" to "' || directory || '"')
  174.                   if (first_word ~= 'CD-INTERNAL') ,
  175.                      | (Upper(directory) ~= Upper(current_directory)) ,
  176.                   then do
  177.                      Call say_command()
  178.                      Call Pragma('Directory', directory)
  179.                   end
  180.                end
  181.                else do
  182.                   /* "CD" without parameters shows current directory
  183.                    * (like "pwd" under Unix) */
  184.                   Call say_command()
  185.                   Say current_directory
  186.                end
  187.             end
  188.             else do
  189.                /* Execute normal command */
  190.                Call say_command()
  191.                Address Command command
  192.                rv = RC
  193.             end
  194.          end
  195.          else do
  196.             Call say_status(command)
  197.          end
  198.          Call Reply(packet, rv)
  199.  
  200.          if rv > 0 then do
  201.             Call Say_status('Command returned ' || rv)
  202.          end
  203.  
  204.          if ~quit then do
  205.             if show_prompt then do
  206.                Call say_prompt()
  207.             end
  208.          end
  209.       end
  210.    end
  211.  
  212.    Say LF || 'Console ended'
  213.  
  214.    ClosePort(port)
  215. end
  216. else do
  217.    Say 'The port "' || port || '" already exists.'
  218.    exit 10
  219. end
  220.  
  221. exit 0
  222.  
  223. /* Show status message in bold face */
  224. say_status:
  225.    Parse Arg message
  226.    Say ESC || '[1m' || message || ESC || '[0m'
  227.    Return
  228.  
  229. /* Show command about to execute */
  230. say_command:
  231.    /*
  232.    if ~show_prompt then do
  233.       Call say_prompt()
  234.    end
  235.    */
  236.    command_counter = command_counter + 1
  237.    show_prompt = 1
  238.    Call say_status command
  239.    Return
  240.  
  241. /* Show debug message */
  242. say_debug:
  243.    if debug then do
  244.       Parse Arg message
  245.       Say message
  246.    end
  247.    Return
  248.  
  249. say_prompt:
  250.    Call WriteCh('STDOUT', ESC || '[1m> ' || ESC || '[0m')
  251.    show_prompt = 0
  252.    Return
  253.  
  254. /* Signal handler for CLI failures */
  255. Failure:
  256.    Call say_status(LF || 'Command failed')
  257.    Say 'Console ended'
  258.    Exit RC
  259.  
  260. /* Signal handler for accessing unitialized variables */
  261. NoValue:
  262.    message = LF || SIGL SourceLine(SIGL) || LF || ,
  263.              'uninitialized value in line ' || SIGL
  264.    Say message
  265.    Exit 20
  266.  
  267. /****** ugly/add_library **************************************************
  268.  * NAME
  269.  *   add_library -- Add library or abort.
  270.  * FUNCTION
  271.  *   If the requested library exists in "libs:", it is opened AddLib().
  272.  *
  273.  *   Otherwise, `message', prefixed by "Library ... not found.", is
  274.  *   displayed and the program exts with code 20.
  275.  * INPUTS
  276.  *   library - Name of the library to open
  277.  *   version - Minimum library version (0 for any)
  278.  * RESULT
  279.  *   If this function returns, everything was ok.
  280.  **************************************************************************/
  281. add_library: procedure
  282.     Parse Arg library, version, error_message
  283.  
  284.     if ~Show('L', library) then do
  285.         added = 0
  286.         if Exists('libs:' || library) then do
  287.            added = AddLib(library, 0, -30, version)
  288.         end
  289.         if ~added then do
  290.             message = "Library '" || library "'"
  291.             if (version > 0) then do
  292.                 message = message || " version " || version
  293.             end
  294.             message = message || 'not found. ' || error_message
  295.             Say message
  296.             Exit 20
  297.         end
  298.     end
  299.  
  300.     return
  301.  
  302.